Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 01.06.2013, 23:13
Аспирант
Отправить личное сообщение для xintrea Посмотреть профиль Найти все сообщения от xintrea
 
Регистрация: 02.01.2011
Сообщений: 56

В callback функции теряется контекст. Как это обойти?
Разбираюсь значит с загрузкой данных с сервера и событийной моделью в JavaScript.

У меня есть "класс", в нем нужно сделать инит, который включет загрузку данных с сервера и их небольшую обработку. Для инита и загрузки данных используется цепочка функций. Вторая в цепочке инита функция вызывается как callback после получения данных с сервера. В общем, всё как учили.

Код примерно такой:

Код:
function LBTablesWorker() 
{

 // Начало инициализации
 this.init = function(iTeamId) 
 {
  // Загрузка с сервера
  this.load(iTeamId, this.initNext); 
 }; 
 

 // Продолжение инициализации
 this.initNext = function() 
 {
  alert('In LBTablesWorker::initNext()'); // Это сообщение видно
  
  this.calculate(); // Здесь ошибка
 }

 
 // Вот эта функция не вызывается
 this.calculate=function() 
 {
  alert('2*2=4');
 };

 
 // Загрузка данных с сервера
 this.load=function(teamId, callback) 
 {
  var that = this;

  // Получение XML-кода  
  $.xmlrpc({
        url: 'http://'+window.location.host+'/XmlRpcServer',
        methodName: 'getTables',
        params: [teamId],
        success: function(response, status, jqXHR){ that.successLoad(response, status, jqXHR); callback(); },
        error: function(jqXHR, status, error) { that.errorLoad(jqXHR, status, error); }
  });

 };
}
Проблема в том, что по всей видимости, при вызове callback-функции теряется контекст. И в такой функции невозможно вызвать функции собственного же класса.

Ошибка в Opera:
Цитата:
Uncaught exception: TypeError: 'this.calculate' is not a function
Ошибка в FireFox:
Цитата:
TypeError: this.calculate is not a function
initNext

Вопрос. Как это можно обойти? Как правильно вызывать callback-функции, чтобы они выполнялись в контексте того места, которому изначально принадлежат?

Note: Да, я не хочу использовать лямбды, я хочу чтобы мой код был как минимум читабельный.
Ответить с цитированием
  #2 (permalink)  
Старый 01.06.2013, 23:31
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,596

callback.call(this) //или that в вашем случае.
Вызов функции в контексте первого аргумента. Почитать: call, apply.

Дело в том, что функция вызванная как x.func() выполняется в контексте x(за исключением особых случаев), а вызванная как просто func() - в текущем контексте.
x = {
    func: function(){alert(this.a)},
    a : 'x.a'
}
this.a = 'current.a';
func = x.func;

x.func();

func();

func.call({a:'dyn.a'});


P.S. Нет такой уж критической надобности переписывать весь уже написанный код. Если ваша страница\приложение в принципе на работает без полученных данных то юзер так или иначе вынужден будет ждать загрузки.)
__________________
29375, 35

Последний раз редактировалось Aetae, 01.06.2013 в 23:37.
Ответить с цитированием
  #3 (permalink)  
Старый 02.06.2013, 00:33
Аспирант
Отправить личное сообщение для xintrea Посмотреть профиль Найти все сообщения от xintrea
 
Регистрация: 02.01.2011
Сообщений: 56

Сообщение от Aetae Посмотреть сообщение
Дело в том, что функция вызванная как x.func() выполняется в контексте x(за исключением особых случаев), а вызванная как просто func() - в текущем контексте.
Понял.


Сообщение от Aetae Посмотреть сообщение
P.S. Нет такой уж критической надобности переписывать весь уже написанный код. Если ваша страница\приложение в принципе на работает без полученных данных то юзер так или иначе вынужден будет ждать загрузки.)
Да я уже начал перелопачивать. И тут вылазят все новые и новые нюансы.

Есть у меня еще один вопрос.

Предположим, инит объекта вызывается из объекта более "верхнего" уровня. Вот так:

Код:
function UpLevelClass() 
{

 this.init = function() 
 {
  alert('Up level class this 1:'+this);

  worker=new Worker();
  worker.init(this.initNext);
 }; 

 this.initNext = function() 
 {
  alert('Up level class this 2:'+this);
 };

}
Код:
function Worker() 
{

 this.init = function(upLevelCallBack) 
 {
  ... всякие действия для инита

  upLevelCallBack();
 };
Спрашивается, в каком контексте будет выполнена функция initNext()? По-моему, совсем не в контесте класса UpLevelClass.

Теперь вопрос: Как в функции init() класса Worker узнать контекст функции upLevelCallBack? Ведь нам ее надо вызвать в контексте класса UpLevelClass, а не в текущем контексте!
Ответить с цитированием
  #4 (permalink)  
Старый 02.06.2013, 01:27
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,596

Лучше не переписывайте пока это всё не будет для вас явным. Почитайте в каком-нибудь цельном учебнике(например на этом сайте) полностью главы посвящённые функциям.
ИМХО, не имеет смысла давать ответы на конкретный вопрос, ибо эти вопросы без знания будут плодиться бесконечно.
__________________
29375, 35
Ответить с цитированием
  #5 (permalink)  
Старый 02.06.2013, 11:40
Аспирант
Отправить личное сообщение для xintrea Посмотреть профиль Найти все сообщения от xintrea
 
Регистрация: 02.01.2011
Сообщений: 56

Да я читаю в параллель конечно.

Вопрос вполне конкретный. Сейчас собираюсь передавать не просто callback-функцию а массив (context, functionName).

Соответственно вызов будет:

upLevelCallBack.call(context)


Вот нигде этой техники не нашел, может народ как-то по-другому делает?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
form, onclick, function...как это все сплести воедино? Berowz Общие вопросы Javascript 0 04.03.2012 15:06
JSON. Как в callback функции изменить свойство объекта? master_alf jQuery 10 22.04.2010 17:08
1092*0.15=? А на javascript? Как это объяснить бухгатеру? oid Общие вопросы Javascript 15 24.10.2009 12:51
Замыкание - это... Zeroglif Общие вопросы Javascript 11 06.03.2009 22:04
Как проверить существование функции Aderba Общие вопросы Javascript 2 14.11.2008 16:09